package com.cxb.carrecorder;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.*;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.location.LocationManager;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OnInfoListener;
import android.media.ThumbnailUtils;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.MediaStore;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.SurfaceHolder;
import com.amitek.aidl.mqtt.MqttServiceProxy;
import com.cxb.carrecorder.CameraUtils.OnRecordStateChangeListener;
import org.xutils.x;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class VideoRecorder implements PreviewCallback, OnInfoListener,
		OnErrorListener, OnRecordStateChangeListener {

	private Camera mCamera = null;
	// private MediaRecorder mediaRecorder = null;
	private boolean bRecording = false;
	public static boolean bStart = false;
	private boolean bLockFile = false;
	// public static int nDuration = 2;

	private boolean bMute = true;

	private String szPath = null;
	public static String szVideoFile = null;
	public static final String SD_ROOT = x.isDebug() ? "/storage/sdcard0"
			: "/storage/sdcard1";
	// public static final String SD_ROOT = "/mnt/sdcard";
	public static final String VIDEOS_PATH_NORMAL = SD_ROOT
			+ "/CarRecord/NormalFile/";
	public static final String VIDEOS_PATH_SHORT = SD_ROOT
			+ "/CarRecord/ShortFile/";
	public static final String VIDEOS_PATH_LOCKED = SD_ROOT
			+ "/CarRecord/LockedFile/";
	private static final String THUMBNAIL_PATH = SD_ROOT
			+ "/CarRecord/Thumbnail/";
	RecorderListener recorderListener = null;
	byte[] cameraData;
	private Context mContext;
	private OnImageUploadCallBack onImageUploadCallBack;
	public static boolean isTimeFix = true;
	private LocationManager locationManager;

	private final int RECORDER_SHORTVEDIO_START = 1;
	private final int RECORDER_SHORTVEDIO_IDLE = 0;
	private int recorderState = RECORDER_SHORTVEDIO_IDLE;

	private int pics = 50;
	private int pics_index = 0;

	// add by xrx
	private static final String CAMERA_SHARING_PATH = "/mnt/sdcard/CarRecord/Sharing/";
	private static final int MESSAGE_SHARING_OVER = 1000;
	private VideoEncoder mVideoEncoder = null;
	private ICameraService mService;
	private boolean mIsRequestFrame = false;
	private boolean mIsFrameCopying = false;
	private byte[] mFrameData = null;
	private EventCallBack mShareCallBack = null;
	public String mShareFile = null;
	private boolean mIsSharePicture = false;
	public static final int SHARE_TIME = 6;
	private final int STATE_IDLE = 0;
	private final int STATE_ENCODING = 1;
	private final int STATE_CLOSE = 2;
	private int state = STATE_IDLE;
	public static int PREVIEW_WIDTH = 800;
	public static int PREVIEW_HEIGHT = 480;
	public static int RECORD_VIDEO_WIDTH = 1280;
	public static int RECORD_VIDEO_HEIGHT = 720;
	public static int nBitRate = RECORD_VIDEO_WIDTH * RECORD_VIDEO_HEIGHT * 4;
	private SurfaceHolder surfaceHolder;
	private MqttServiceProxy mqttProxy;

	// private final String SERVER_URL="http://s.ami-tek.cn/";
	private byte[] preBuffer;

	private static VideoRecorder mVideoRecorder;

	private PersistUtils persistUtils;



	public static VideoRecorder getInstance(SurfaceHolder surfaceHolder,
			Context context) {
		if (mVideoRecorder == null) {
			mVideoRecorder = new VideoRecorder(surfaceHolder, context);
		}
		return mVideoRecorder;
	}

	public void clearShareImageCache() {
		new File(CAMERA_SHARING_PATH).delete();
	}

	private VideoRecorder(SurfaceHolder surfaceHolder, Context context) {
		this.bRecording = false;
		this.bStart = false;
		this.surfaceHolder = surfaceHolder;
		this.mContext = context;
		persistUtils = new PersistUtils(mContext);
		locationManager = (LocationManager) mContext
				.getSystemService(Context.LOCATION_SERVICE);
		if (isTestMode()) {
			return;
		}
		try {
			try {
				// mCamera =
				// CameraUtils.openCamera(CameraInfo.CAMERA_FACING_BACK);
				CameraUtils.preparePreview(surfaceHolder, PREVIEW_WIDTH,
						PREVIEW_HEIGHT, ImageFormat.NV21, 1, context
								.getResources().getConfiguration().orientation);
				mCamera = CameraUtils.getCurrentCamera();
				CameraUtils.startPreviewWithBuffer(this, null);
				CameraUtils.setOnRecordStateChangeListener(this);

				// initCameraService();
			} catch (Exception e) {

				start(false);
				CameraUtils.releaseCamera();

			}
		} catch (Exception e) {
			CarRecorderDebug.printfPhotoLog(e);
		}
		persistUtils.setPreviewPushEnable(false);
		mqttProxy = new MqttServiceProxy(context);
		mqttProxy.bindService();

	}

	public boolean isBStart() {
		return bStart;
	}

	public Bitmap Bytes2Bimap(byte[] b) {
		if (b.length != 0) {
			return BitmapFactory.decodeByteArray(b, 0, b.length);
		} else {
			return null;
		}
	}

	private boolean isTestMode() {
		try {

			ActivityManager manager = (ActivityManager) mContext
					.getSystemService(Context.ACTIVITY_SERVICE);
			RunningTaskInfo info = manager.getRunningTasks(1).get(0);
			String packageName = info.topActivity.getPackageName(); // 闁告牕鎳庨幃锟�
			return "com.zzx.factorytest".equals(packageName);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public void stopPreView() {
		if (CameraUtils.isRecordStarted()) {
			CameraUtils.stopRecord();
		}
		CameraUtils.stopPreview();
		CameraUtils.releaseCamera();

	}

	public void setPreviewDisplay(SurfaceHolder sf) {
		try {
			mCamera.setPreviewDisplay(sf);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public interface RecorderListener {
		public void onStarted();

		public void onStoped(boolean bStart);

		public void onLocked(boolean bLocked);

		public void onMute(boolean bMute);
	}

	public void setRecorderListener(RecorderListener listener) {
		recorderListener = listener;
	}

	public void removeRecorderListener() {
		recorderListener = null;
	}

	public boolean startRecord() {

		if (!android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			return false;
		}

		// add by xrx
		//
		try {

			File fileDir = new File(VIDEOS_PATH_NORMAL);
			boolean goonEnable = false;
			if (!fileDir.exists())
				goonEnable = fileDir.mkdirs();
		//	Log.e("debug", "goonEnable:"+goonEnable + " path: " + fileDir.getAbsolutePath());
			fileDir = null;
			fileDir = new File(THUMBNAIL_PATH);
			if (!fileDir.exists())
				goonEnable = fileDir.mkdirs();
		//	Log.e("debug", "goonEnable:"+goonEnable + " path: " + fileDir.getAbsolutePath());
			fileDir = null;

			szVideoFile = VIDEOS_PATH_NORMAL
					+ new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA)
							.format(new Date()) + ".temp";

			CameraUtils.prepareRecord(surfaceHolder, RECORD_VIDEO_WIDTH,
					RECORD_VIDEO_HEIGHT, persistUtils.getRecordAudioEnable(),
					30, nBitRate, 1000 * 60 * persistUtils.getRecordTime(),
					szVideoFile);
			if (CameraUtils.startRecord(this, this)) {

				bRecording = true;
				if (recorderListener != null) {
					recorderListener.onStarted();
				}
			}
			isUploadImage1 = false;
			isUploadImage2 = false;

			return true;

		} catch (Exception e) {

			start(false);
		}
		return false;
	}

	public void cameraUnlock() {
		mCamera.unlock();
	}

	private boolean stopRecord() {
		boolean bRet = false;

		CameraUtils.stopRecord();
		if (szVideoFile != null) {
			if (szVideoFile.endsWith("temp")) {
				File videoFile = new File(szVideoFile);
				szVideoFile = szVideoFile.replace("temp", "3gp");
				videoFile.renameTo(new File(szVideoFile));
				// add by xrx
				getVideoThumbnailFile(szVideoFile);
				CarRecorderDebug.printfRECORDERLog("new file renameTo "
						+ szVideoFile);
			}
		}
		try {
			mCamera.lock();
			CarRecorderDebug.printfRECORDERLog("mCamera.lock() ");
			Thread.sleep(100);
		} catch (Exception e) {

			e.printStackTrace();
		}

		checkLockFile();
		bRet = true;
		bRecording = false;

		if (recorderListener != null)// 鐟滅増鎸告晶鐘绘閿熺瓔娲ｇ憸鐗堟礀閸庢岸鎯冮崟顓炐﹂柟顑挎缁楀懓銇愰弴鐐插壖闁稿绮嶉娑欑閸℃冻鎷烽弶鈺佹搐濞叉牜鎷崘顕嗘嫹闁活厹鍎抽弫銈夊箣閿燂拷
		{
			recorderListener.onStoped(bStart);

		}

		return bRet;
	}

	private void notyfyMediaAdd(File file) {
		// Intent mediaScanIntent = new Intent(
		// Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
		// Uri contentUri = Uri.fromFile(file);
		// mediaScanIntent.setData(contentUri);
		// mContext.sendBroadcast(mediaScanIntent);
	}

	public boolean start(boolean start) {
		Log.i("test", "media recorder start=" + start);
		if (isTestMode()) {
			return false;
		}
		if (mCamera == null) {
			return false;
		}
		bStart = start;
		if (bStart) {
			return startRecord();
		} else {
			return stopRecord();
		}
	}

	public boolean isRecording() {
		return CameraUtils.isRecordStarted();
	}

	public void releaseCamera() {
		CameraUtils.stopRecord();
		CameraUtils.stopPreview();

	}

	private void checkLockFile() {
		if (szVideoFile != null && bLockFile) {
			File fileDir = new File(VIDEOS_PATH_LOCKED);
			if (!fileDir.exists())
				fileDir.mkdirs();
			fileDir = null;

			String szLockFile = VIDEOS_PATH_LOCKED
					+ szVideoFile.substring(szVideoFile
							.lastIndexOf(File.separator)
							+ File.separator.length());
			File file = new File(szVideoFile);
			file.renameTo(new File(szLockFile));
			szVideoFile = null;
			file = null;

			bLockFile = false;
			if (recorderListener != null)
				recorderListener.onLocked(bLockFile);
		}
		System.gc();
	}

	public void LockFile() {
		bLockFile = true;
		if (recorderListener != null)
			recorderListener.onLocked(bLockFile);
	}

	public boolean isLocked() {
		return bLockFile;
	}

	public void release() {
		// start(false);
		removeRecorderListener();
		if (mCamera != null) {
			mCamera.stopPreview();
			mCamera.lock();
			mCamera.release();
			mCamera = null;
		}
	}

	@Override
	protected void finalize() throws Throwable {
		release();
		super.finalize();
	}

	boolean isUploadImage1 = false;
	boolean isUploadImage2 = false;

	public void uploadImage(final Context context) throws Exception {
		CarRecorderDebug.printfPhotoLog("uploadImage");
		isUploadImage1 = false;
		PictureCallback pictureCallback = new Camera.PictureCallback() {

			@Override
			public void onPictureTaken(final byte[] data, final Camera arg1) {
				CarRecorderDebug.printfPhotoLog("onPictureTaken");
				try {
					if (!isUploadImage1) {
						new Thread() {
							public void run() {
								try {
									CarRecorderDebug
											.printfPhotoLog("onPictureTaken run..");
									upload2Server(context, data, arg1);
								} catch (Exception e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							};
						}.start();
						isUploadImage1 = true;

					}
				} catch (Exception e) {
					CarRecorderDebug.printfPhotoLog("onPreviewFrame e " + e);
					e.printStackTrace();
				}
			}
		};
		mCamera.takePicture(null, null, pictureCallback);
	}

	public void upload2Server(Context contexts, byte[] data, Camera arg1)
			throws Exception {

		TelephonyManager telephonyManager = (TelephonyManager) contexts
				.getSystemService(Context.TELEPHONY_SERVICE);
		final String path = "/mnt/sdcard/" + System.currentTimeMillis() + "_"
				+ telephonyManager.getDeviceId() + ".jpg";

		File imageTmpFile = new File(path);
		if (imageTmpFile.exists()) {
			imageTmpFile.delete();
		}

		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = 2;
		Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		bitmap = drawTextToBitmap(mContext, bitmap,
				sdf.format(System.currentTimeMillis()), 40);

		bitmap = zoomImg(bitmap, 0.5f);
		FileOutputStream fileout = new FileOutputStream(new File(path));
		bitmap.compress(CompressFormat.JPEG, 80, fileout);
		bitmap.recycle();
		fileout.close();

		CarRecorderDebug.printfPhotoLog("path" + path);
		CarRecorderDebug.printfPhotoLog("startService.....");

		new Thread() {
			public void run() {
				try {
					mqttProxy.sendTrackStopImage(path);
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			};
		}.start();
		// Intent i = new Intent();
		// i.setClassName("com.cxb", "com.amitek.impl.MqttService");
		// i.setAction("ACTION_SEND_SHUTDOWN_IMAGE_FILE");
		// i.putExtra("EXTRA_IMAGE", path);
		// mContext.startService(i);

	}

	public void uploadPre10sImage(Context context,
			OnImageUploadCallBack uploadCallBack) {
		new Thread(new SaveCacheImageTask(context, uploadCallBack)).start();
	}

	class SaveCacheImageTask implements Runnable {

		private Context mContext;

		public SaveCacheImageTask(Context context,
				OnImageUploadCallBack onImageUploadCallBack) {
			// TODO Auto-generated constructor stub
			mContext = context;
			VideoRecorder.this.onImageUploadCallBack = onImageUploadCallBack;
		}

		public void run() {

			try {

				List<File> videoList = new ArrayList<File>();
				File normalVideoFile = new File(VIDEOS_PATH_NORMAL);
				File lockVideoFile = new File(VIDEOS_PATH_LOCKED);
				if (normalVideoFile.exists()) {
					File[] subFile = normalVideoFile.listFiles();
					for (File f : subFile) {
						if (f.getName().endsWith("3gp")) {
							videoList.add(f);
						}
					}
				}
				if (lockVideoFile.exists()) {
					File[] subFile = lockVideoFile.listFiles();
					for (File f : subFile) {
						if (f.getName().endsWith("3gp")) {
							videoList.add(f);
						}
					}
				}

				if (videoList.size() < 1) {
					return;
				}
				Collections.sort(videoList, new Comparator<File>() {

					@Override
					public int compare(File lhs, File rhs) {
						if (lhs.lastModified() == rhs.lastModified()) {
							return 0;
						} else if (lhs.lastModified() > rhs.lastModified()) {
							return -1;
						} else if (lhs.lastModified() < rhs.lastModified()) {
							return 1;
						}
						return 0;
					}
				});

				String dataPath = videoList.get(0).getAbsolutePath();
				Log.i("test", "get images from video " + dataPath);
				MediaMetadataRetriever retriever = new MediaMetadataRetriever();
				retriever.setDataSource(dataPath);
				String time = retriever
						.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
				// 闁告瑦鐗曠欢杈╂喆閸℃侗鏆ラ柣銊ュ閺嗚鲸鎯旈敓浠嬪础閺囨氨绉村☉鎾规椤拷
				int seconds = Integer.valueOf(time) / 1000;

				// if (seconds <= 10) {
				// startTime = seconds;
				// }

				Bitmap bitmap1 = null;
				int lastShotcut_time = 12;

				if (seconds <= 12) {
					// CarRecorderDebug.printfPhotoLog(" seconds <= 10 ");
					// bitmap1 = retriever.getFrameAtTime(1 * 1000 * 1000,
					// MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
					long distance_time = 0l;
					if (videoList.size() > 1)
						distance_time = videoList.get(0).lastModified()
								- seconds * 1000
								- videoList.get(1).lastModified();
					if (distance_time > 12 * 1000 || videoList.size() <= 1) {
						CarRecorderDebug.printfPhotoLog(" 来自第一个 ");
						bitmap1 = retriever.getFrameAtTime(1 * 1000 * 1000,
								MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
					} else {
						CarRecorderDebug.printfPhotoLog(" 跳转第二个");
						dataPath = videoList.get(1).getAbsolutePath();
						retriever.setDataSource(dataPath);

						int getTime = 12 - seconds
								- (int) (distance_time / 1000);

						if (getTime < 1) {
							lastShotcut_time = 1;
						} else {
							lastShotcut_time = getTime;
						}
						CarRecorderDebug.printfPhotoLog(" 跳转第二个 当前 " + seconds
								+ " 相隔 " + (int) (distance_time / 1000)
								+ " 最后 " + lastShotcut_time + "秒");
					}
				}
				// else
				if (bitmap1 == null) {
					CarRecorderDebug.printfPhotoLog(" 来自第二个 ");
					time = retriever
							.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
					seconds = Integer.valueOf(time) / 1000;
					int getTimeS = (seconds - lastShotcut_time) * 1000 * 1000;
					if (seconds <= lastShotcut_time) {
						getTimeS = 1 * 1000 * 1000;
					}
					bitmap1 = retriever.getFrameAtTime(getTimeS,
							MediaMetadataRetriever.OPTION_CLOSEST_SYNC);

					// bitmap2 = retriever.getFrameAtTime(seconds * 1000 * 1000,
					// MediaMetadataRetriever.OPTION_PREVIOUS_SYNC);
					// time2 = new File(dataPath).lastModified();
				}

				CarRecorderDebug.printfPhotoLog("requestFilePost");

				TelephonyManager telephonyManager = (TelephonyManager) mContext
						.getSystemService(Context.TELEPHONY_SERVICE);
				final String path = "/sdcard/" + System.currentTimeMillis()
						+ "_" + telephonyManager.getDeviceId() + ".jpg";
				CarRecorderDebug.printfPhotoLog("path " + path);
				FileOutputStream fileout = new FileOutputStream(new File(path));

				bitmap1.compress(CompressFormat.JPEG, 80, fileout);
				bitmap1.recycle();
				bitmap1 = null;

				CarRecorderDebug
						.printfPhotoLog("actionSendShutDownBitmap.....");

				if (!PreviewService.isPowerOffing) {
					CarRecorderDebug.printfRECORDERLog("涓嶅湪鍏虫満鐘舵��");
					return;
				}
				CarRecorderDebug.printfPhotoLog("startService.....");

				new Thread() {
					public void run() {
						try {
							mqttProxy.sendTrackStopImage(path);
						} catch (RemoteException e) {
							e.printStackTrace();
						}
					};
				}.start();

				fileout.close();
				if (onImageUploadCallBack != null) {
					onImageUploadCallBack.onImageComplete();
				}

			} catch (Exception e) {

				e.printStackTrace();
			}

		}

	}

	public static Bitmap zoomImg(Bitmap bm, float rate) {

		int width = bm.getWidth();
		int height = bm.getHeight();

		Matrix matrix = new Matrix();
		matrix.postScale(rate, rate);
		Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
				true);
		return newbm;
	}

	public Bitmap drawTextToBitmap(Context gContext, Bitmap bitmap,
			String gText, int textsize) {

		android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();

		// set default bitmap config if none
		if (bitmapConfig == null) {
			bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
		}
		// resource bitmaps are imutable,
		// so we need to convert it to mutable one
		bitmap = bitmap.copy(bitmapConfig, true);

		Canvas canvas = new Canvas(bitmap);
		// new antialised Paint
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		// text color - #3D3D3D
		paint.setColor(Color.RED);
		paint.setTextSize((int) (textsize));
		paint.setDither(true); // 闁兼儳鍢茶ぐ鍥╂崉閻斿摜顏搁柡鍛濞堟垿宕堕幆褍鍓奸梺鎻掓处閻楋拷
		paint.setFilterBitmap(true);// 閺夆晛娲﹂幎銈嗙▔閿熺晫鏄�
		Rect bounds = new Rect();
		paint.getTextBounds(gText, 0, gText.length(), bounds);
		int x = bitmap.getWidth() - bounds.width() - 50;
		int y = 50;
		canvas.drawText(gText, x, y, paint);
		return bitmap;
	}

	public Bitmap drawTextToBitmap2(Context gContext, Bitmap bitmap,
			String gText, int textsize) {

		android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();

		// set default bitmap config if none
		if (bitmapConfig == null) {
			bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
		}
		// resource bitmaps are imutable,
		// so we need to convert it to mutable one
		bitmap = bitmap.copy(bitmapConfig, true);

		Canvas canvas = new Canvas(bitmap);
		// new antialised Paint
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		// text color - #3D3D3D
		paint.setColor(Color.RED);
		paint.setTextSize((int) (textsize));
		paint.setDither(true); // 闁兼儳鍢茶ぐ鍥╂崉閻斿摜顏搁柡鍛濞堟垿宕堕幆褍鍓奸梺鎻掓处閻楋拷
		paint.setFilterBitmap(true);// 閺夆晛娲﹂幎銈嗙▔閿熺晫鏄�
		Rect bounds = new Rect();
		paint.getTextBounds(gText, 0, gText.length(), bounds);
		int x = bitmap.getWidth() - bounds.width() - 20;
		int y = 50;
		canvas.drawText(gText, x, y, paint);
		return bitmap;
	}

	public void actionSendShutDownBitmap(Context ctx, byte[] bitmapData) {
		CarRecorderDebug.printfPhotoLog("bitmapData" + bitmapData);

		TelephonyManager telephonyManager = (TelephonyManager) ctx
				.getSystemService(Context.TELEPHONY_SERVICE);
		final String path = "/mnt/sdcard/" + System.currentTimeMillis() + "_"
				+ telephonyManager.getDeviceId() + ".jpg";

		takePicture(bitmapData, null, path);

		CarRecorderDebug.printfPhotoLog("actionSendShutDownBitmap.....");
		if (!PreviewService.isPowerOffing) {
			CarRecorderDebug.printfRECORDERLog("涓嶅湪鍏虫満鐘舵��");
			return;
		}
		CarRecorderDebug.printfPhotoLog("startService.....");
		// Intent i = new Intent();
		// i.setClassName("com.cxb", "com.amitek.impl.MqttService");
		// i.setAction("ACTION_SEND_SHUTDOWN_IMAGE_FILE");
		// i.putExtra("EXTRA_IMAGE", path);
		// ctx.startService(i);
		try {
			mqttProxy.sendTrackStopImage(path);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	private void saveBitmapFile(String filename, byte[] data)
			throws IOException {
		File fileDir = new File(VIDEOS_PATH_SHORT);
		Camera.Parameters parameters = mCamera.getParameters();
		if (!fileDir.exists())
			fileDir.mkdirs();
		File imageFile = new File(filename);

		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(imageFile));
		YuvImage yuvimage = new YuvImage(data, ImageFormat.NV21, PREVIEW_WIDTH,
				PREVIEW_HEIGHT, null);
		yuvimage.compressToJpeg(new Rect(0, 0, 480, 320), 100, bos);
		bos.flush();
		bos.close();
	}

	// add by xrx
	public void startShotPicture(EventCallBack shareCallBack) {
		File fileDir = new File(CAMERA_SHARING_PATH);
		if (!fileDir.exists()) {
			fileDir.mkdirs();
		}
		mIsSharePicture = true;
		persistUtils.setPreviewPushEnable(true);
		mShareCallBack = shareCallBack;

	}

	private void getSharePictureFile(byte[] data) {
		Camera.Parameters parameters = mCamera.getParameters();
		SimpleDateFormat storeDate = new SimpleDateFormat("yyyyMMddHHmmss");
		String times = storeDate.format(new Date(System.currentTimeMillis()));
		mShareFile = CAMERA_SHARING_PATH + times + ".jpg";
		File imageFile = new File(mShareFile);

		VideoEncoder.getFrameJpegFileWithTime(mShareFile, data,
				parameters.getPreviewFormat(), PREVIEW_WIDTH, PREVIEW_HEIGHT, 1f, isRecording());

		mIsSharePicture = false;
		persistUtils.setPreviewPushEnable(false);
		mShareCallBack.onPictureShareComplete(mShareFile);
	}

	private void takePicture(byte[] data, Camera camera, String name) {
		FileOutputStream outSteam = null;
		File fileDir = new File(CAMERA_SHARING_PATH);
		if (!fileDir.exists())
			fileDir.mkdirs();
		Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
				null);
		Matrix matrix = new Matrix();
		// matrix.postScale(0.5f, 0.5f);
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();

		Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, width, height,
				matrix, true);

		try {
			BufferedOutputStream bos = new BufferedOutputStream(
					new FileOutputStream(name));
			newBmp.compress(Bitmap.CompressFormat.JPEG, 80, bos);
			CarRecorderDebug.printfPhotoLog("pumkid " + name);
			bos.flush();
			bos.close();
		} catch (IOException e) {
			e.printStackTrace();
			CarRecorderDebug.printfPhotoLog(e);
		}

		if (camera != null) {
			camera.stopPreview();
			camera.startPreview();
			mShareCallBack.onPictureShareComplete(mShareFile);
			mFrameData = null;
		}

	}

	@Override
	public void onPreviewFrame(final byte[] data, final Camera camera) {
		Log.i("test", "onPreviewFrame mIsRequestFrame=" + mIsRequestFrame);

		x.task().run(new Runnable() {

			@Override
			public void run() {
				try {

					try {
						if (mService != null) {
							mService.getCameraFrame(data);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}

					if (mIsRequestFrame) {

//						byte[] resizedImage = PicCrap.ResizeImage(
//								(short) PREVIEW_WIDTH, (short) PREVIEW_HEIGHT,
//								data, (short) 4);
						copyFrameData(data);
					} else if (mIsSharePicture) {
						Log.i("test", "mIsSharePicture");
						mIsSharePicture = false;
//						byte[] resizedImage = PicCrap.ResizeImage(
//								(short) PREVIEW_WIDTH, (short) PREVIEW_HEIGHT,
//								data, (short) 4);
						Log.i("test", "mIsSharePicture ok");
						getSharePictureFile(data);
					} 
				} catch (Exception e) {
					e.printStackTrace();
				}
				camera.addCallbackBuffer(data);

			}
		});

	}

	ThreadShare mThreadShare;

	public void startEncodeVideo(EventCallBack shareCallBack) {
		File fileDir = new File(CAMERA_SHARING_PATH);
		if (!fileDir.exists())
			fileDir.mkdirs();
		SimpleDateFormat storeDate = new SimpleDateFormat("yyyyMMddHHmmss");
		String times = storeDate.format(new Date(System.currentTimeMillis()));
		Camera.Parameters parameters = mCamera.getParameters();
		List<Camera.Size> previewSize = parameters.getSupportedPreviewSizes();
		Camera.Size maxPreviewSize = previewSize.get(previewSize.size() - 1);
		mShareCallBack = shareCallBack;
		mVideoEncoder = new VideoEncoder(PREVIEW_WIDTH, PREVIEW_HEIGHT, 10, 250000);
		mShareFile = CAMERA_SHARING_PATH + times + ".mp4";
		mVideoEncoder.startEncode(mShareFile);
		persistUtils.setPreviewPushEnable(true);
		if (state == STATE_IDLE)
			new Thread(new ThreadShare()).start();
	}

	public void stopEncodeVideo() {
		if (mVideoEncoder != null) {
			mVideoEncoder.stopEncode();
		}
	}

	public void cancelShareVideo() {
		stopEncodeVideo();
		// File file = new File(mShareFile);
		// file.delete();
		RootContext.runCommandForResult("rm " + CAMERA_SHARING_PATH + "*");
	}

	class ThreadShare implements Runnable {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			/*
			 * try { Thread.sleep(5000); } catch (InterruptedException e) { //
			 * TODO Auto-generated catch block e.printStackTrace(); }
			 * stopEncodeVideo();
			 */
			System.out.println();
			while ((!mVideoEncoder.isEncodeComplete())
					&& (mVideoEncoder.getEncodeTime() <= 1000 * SHARE_TIME)) {
				if (getFrameData() == null)
					break;
				state = STATE_ENCODING;
				mVideoEncoder.encode(mFrameData, isRecording());
			}
			System.out.println();
			persistUtils.setPreviewPushEnable(false);
			state = STATE_CLOSE;
			mVideoEncoder.stopEncode();
			mShareCallBack.onVideoComplete(mShareFile);
			state = STATE_IDLE;
		} 
	} 
   
	public long getShareVideoDuration() {
		if (mVideoEncoder == null)
			return 0;
		return mVideoEncoder.getEncodeTime();
	}

	public byte[] copyFrameData(byte[] data) {
		if (mIsRequestFrame) {
			mIsRequestFrame = false;
		
			if (mFrameData == null)
				mFrameData = new byte[data.length];
			System.arraycopy(data, 0, mFrameData, 0, data.length);
			mIsFrameCopying = false;
		}
		return mFrameData;
	}

	public byte[] getFrameData() {
		Log.i("test", "onPreviewFrame getFrameData");
		mIsFrameCopying = true;
		mIsRequestFrame = true;
		persistUtils.setPreviewPushEnable(true);
		while (mIsFrameCopying == true) {
			try {
				Thread.sleep(5);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return mFrameData;
	}

	private ServiceConnection mConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			mService = ICameraService.Stub.asInterface(service);
			try {
				mService.registerCallBack(mCallBack);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			try {
				mService.unregisterCallBack();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			mService = null;
		}

	};

	private void initCameraService() {
		Intent intent = new Intent("com.cxb.carrecorder.CameraService");
		boolean ret = mContext.bindService(intent, mConnection,
				Context.BIND_AUTO_CREATE);
	}

	private void releaseCameraService() {
		if (mConnection != null) {
			mContext.unbindService(mConnection);
			mConnection = null;
		}

	}

	private final ICameraCallBack.Stub mCallBack = new ICameraCallBack.Stub() {

		@Override
		public void onCameraFrameCallBack(byte[] data) throws RemoteException {
			// TODO Auto-generated method stub
			Log.v("test2", "sssssssssssssssss");
		}

	};

	static public boolean isFileExist(String fileName) {
		try {
			File f = new File(fileName);
			if (!f.exists()) {
				return false;
			}

		} catch (Exception e) {
			// TODO: handle exception
			return false;
		}
		return true;
	}

	static public String GetFileName(String filePath) {

		int start = filePath.lastIndexOf("/");
		int end = filePath.lastIndexOf(".");
		if (start != -1 && end != -1) {
			return filePath.substring(start + 1, end);
		} else {
			return null;
		}
	}

	static public String getThumbnailFileName(String videoFile) {
		return THUMBNAIL_PATH + GetFileName(videoFile) + ".jpg";
	}

	static public String getVideoThumbnailFile(String videoFile) {
		Bitmap bitmap = null;
		String thumbnailFileName = null;

		bitmap = ThumbnailUtils.createVideoThumbnail(videoFile,
				MediaStore.Images.Thumbnails.MICRO_KIND);
		if (bitmap != null) {
			bitmap = ThumbnailUtils.extractThumbnail(bitmap, 120, 80,
					ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
			if (bitmap != null) {
				thumbnailFileName = getThumbnailFileName(videoFile);
				File thumbnailFile = new File(thumbnailFileName);
				if (thumbnailFile.exists()) {
					thumbnailFile.delete();
				}
				FileOutputStream foutStream = null;
				try {
					foutStream = new FileOutputStream(thumbnailFile);
					bitmap.compress(Bitmap.CompressFormat.JPEG, 80, foutStream);
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				bitmap = null;
			}
		}

		return thumbnailFileName;
	}

	@Override
	public void onError(MediaRecorder mr, int what, int extra) {
		start(false);

	}

	@Override
	public void onInfo(MediaRecorder mr, int what, int extra) {
		switch (what) {
		case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED: {

			stopRecord();
			notyfyMediaAdd(new File(szVideoFile));
		}
			break;

		case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED: {

			stopRecord();
			notyfyMediaAdd(new File(szVideoFile));
		}
			break;

		case MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN: {

			start(false);
		}
			break;
		}
	}

	@Override
	public void onRecordStateChange(boolean isRecording) {
		if (isRecording) {
			recorderListener.onStarted();
		} else {
			recorderListener.onStoped(false);
		}

	}

}
